from math import *
from numpy import *
import matplotlib.pyplot as plt

# EJERCICIO 1 =================================================================
print("Ejercicio 2 " + "="*50)

x_i = 0.5

def expansion_taylor_ex(x_i, N):
    suma = 0
    
    for n in range(N+1):
        termino = ((x_i)**n) / factorial(n)
        suma += termino
        
    return suma

print(f"\nn=3: \t{expansion_taylor_ex(x_i, 3):.7f}\nn=4: \t{expansion_taylor_ex(x_i, 4):.7f}\nn=5: \t{expansion_taylor_ex(x_i, 5):.7f}\n")

# EJERCICIO 2 =================================================================
print("Ejercicio 2 " + "="*50)
x_0 = 0.5
h = 0.25

def f(x):
    return -0.1*x**4 -0.15*x**3 -0.5*x**2 -0.25*x +1.2

def diff_alante(f, x_0, h):
    return (f(x_0+h)-f(x_0))/h

def diff_atras(f, x_0, h):
    return (-f(x_0-h)+f(x_0))/h

def diff_centrada(f, x_0, h):
    return (f(x_0+h)-f(x_0-h))/(2*h)

print(f"\nec.5:\t{diff_alante(f, x_0, h):.4f}\nec.8:\t{diff_atras(f, x_0, h):.4f}\nec.10:\t{diff_centrada(f, x_0, h):.4f}\n")

# EJERCICIO 3 =================================================================
print("Ejercicio 3 " + "="*50)
print("")

x = [0.6, 0.7, 0.8, 0.9, 1.0]
phi_x = [1.24110, 1.40917, 1.66863, 2.07301, 2.71828]

h = 0.1
x_0 = 0.8

def diff_centrada_phi_x(phi_x, x_0, h, i):
    ind = x.index(x_0)
    return (phi_x[ind + i] - phi_x[ind - i])/(2*i*h)

def diff_cuatro_puntos_phi_x(phi_x, x_0, h, i):
    ind = x.index(x_0)
    return (phi_x[ind - 2*i] - phi_x[ind + 2*i] + 8*phi_x[ind + i] - 8*phi_x[ind - i])/(12*h*i)

for i in range(2, 0, -1):
    print(f"ec. 10, h = {h*i}: \t {diff_centrada_phi_x(phi_x, x_0, h, i):.5f}")
print(f"ec. 15, h = {h}: \t {diff_cuatro_puntos_phi_x(phi_x, x_0, h, 1):.5f}")

print("")

# EJERCICIO 4 =================================================================
print("Ejercicio 4 " + "="*50)
print("")

h = 0.15
x_0 = [-2.5, -2.0, -1.5, -1.0]

def funcion(x):
    return x*sqrt(9-x**2) + 9*arcsin(x/3)

def derivada_funcion(x):
    return 3/(sqrt(1-((x**2)/9))) + sqrt(9-x**2) - (x**2)/(sqrt(9-x**2))

# Funcion derivada hacia adelante

derivada_en_x0 = [diff_alante(funcion, i, h) for i in x_0]

print(f"derivada hacia adelante, h = {h}")
for i in x_0:
    print(f"\ten x0 = {i}:\t{diff_alante(funcion, i, h):.5f}")

x = linspace(-2.75, 2.75, 100)
y = derivada_funcion(x)

plt.scatter(x_0, derivada_en_x0,color="red", label="ec.15, h=0.15")
plt.plot(x, y, label="f'(x) exacta")
plt.xlabel("x")
plt.ylabel("df/dx")
plt.legend(loc="upper right")
plt.grid()
plt.show()